package youcheng.work.view_zhexian;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class BlueToothActivity extends AppCompatActivity implements View.OnClickListener{
    private Toast mToast;

    public static final int REQUEST_CODE = 0;
    private BlueToothControl mController = new BlueToothControl();// 蓝牙适配器
    private List<BluetoothDevice> mDeviceList = new ArrayList<>();// 已经发现的设备列表
    private List<BluetoothDevice> mBondedDevice = new ArrayList<>();//发现的设备列表里已经绑定的设备列表
    private DeviceAdapter mAdapter;//scoreview设备列表
    private ListView mListview;
    ArrayAdapter<String> adapter = null;
    private String TAG = "text";

    public static final int RECV_VIEW = 0;
    public static final int NOTICE_VIEW = 1;
    public static final int STATUS_CONNECT = 3;
    public static final String PROTOCOL_SCHEME_RFCOMM = "btspp";

    // 服务端蓝牙socket
    private BluetoothServerSocket mServerSocket;
    // 客户端蓝牙socket
    private BluetoothSocket socket;

    private TextView noticeView = null;
    ScrollView scrollView = null;
    private TextView recvView = null;
    private EditText sendText = null;
    private Button clearRecvView = null;
    private Button deleteEdit = null;
    private Button send = null;
    private Button turnOnOff = null;



    private ConnectThread connectThread = null;
    private ConnectedThread connectedThread = null;
    private ServerThread serverThread = null;

    public BluetoothAdapter bluetoothAdapter = null;


    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_blue_tooth);

/* blue_tooth控件初始化声明*/
        noticeView = (TextView) findViewById(R.id.notice_view);//提示栏控件
        scrollView = (ScrollView) findViewById(R.id.scroll_view);//滑动屏控件
        recvView = (TextView) findViewById(R.id.recv_view);//接收控件
        sendText = (EditText) findViewById(R.id.send_text);//发送编辑框控件




        initUI();//初始化scoreview控件

        /*                 注册广播接收器                              */
        IntentFilter filter = new IntentFilter();
        //开始查找
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        //结束查找
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        //查找设备 获取查找到的设备的结果
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        //设备扫描模式改变，可发现模式开启会接收到广播 结束也会接受到广播
        filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        //绑定状态
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

        registerReceiver(mReceiver, filter);//将注册好的信息和广播绑定起来


        // 获取BluetoothAdapter
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            // Device does not support Bluetooth
            return;
        }
        /* 打开蓝牙*/
        mController.turnOnBlueTooth(this, REQUEST_CODE);
        if (!bluetoothAdapter.isEnabled()) {
            noticeView.setText("蓝牙未开启");
        }
        else {
            noticeView.setText("蓝牙已开启");
        }
        /* setOnClickListener代表设置事件处理的监听器，this代表就是所在的类，implements OnClickListener就代表实现监听器的接口，而public void onClick(View v)
        函数就代表事件的处理函数，就是你点击startButton 按钮就会进入到onClick函数里面 */
        clearRecvView = (Button) findViewById(R.id.clear_recv_view);//清除控件
        send = (Button) findViewById(R.id.send);//发送控件
        turnOnOff = (Button)findViewById(R.id.turn_on_off);//关闭控件
        deleteEdit = (Button) findViewById(R.id.delete_edit);

        clearRecvView.setOnClickListener(this);
        send.setOnClickListener(this);
        turnOnOff.setOnClickListener(this);
        deleteEdit.setOnClickListener(this);

    }
    /////////////////////////////////////////////////////////////////////////////////////
    /* 打印工具 */
    public void showToast(String text) {
        if (mToast == null) {
            mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
        } else {
            mToast.setText(text);
        }
        mToast.show();
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        //给菜单充气；这会将项目添加到操作栏（如果存在）。
        getMenuInflater().inflate(R.menu.menu_options, menu);
        return true;
    }

    //初始化UI控件
    private void initUI() {
        mListview = (ListView) findViewById(R.id.device_list);
        mAdapter = new DeviceAdapter(mDeviceList, this);
        mListview.setAdapter(mAdapter);
        //给listview设置点击事件
        mListview.setOnItemClickListener(bondDeviceClick);
    }
    /*
        获取蓝牙权限
         */
    private void requestBlueToothPermission() {
        if(Build.VERSION.SDK_INT>=6.0){
            ActivityCompat.requestPermissions(this,new String[]{
                    Manifest.permission.ACCESS_FINE_LOCATION
            },1);
        }
    }

    /*
     获取权限回调
    */
    public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) {
        Log.i(TAG,"进入回调");
        switch (requestCode){
            case 1:
                if (grantResults.length>0&&grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    Log.i(TAG,"获取蓝牙权限成功");
                }
                return;
        }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////
    /* 定义广播接收器，重写onReceive方法，根据已注册的广播判断发生了什么事*/
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();//设置一个行为
            /* 开始查找*/
            if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
                setProgressBarIndeterminateVisibility(true);//进度条
                //初始化数据列表
                mDeviceList.clear();
                mAdapter.notifyDataSetChanged();//更新列表
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                /* 查找结束*/
                setProgressBarIndeterminateVisibility(false);//查找到后将进度条隐藏掉
            } else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                /* 找到蓝牙设备 */
                //由action_found的这个广播添加到devicelist
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                Log.d(TAG, "ACTION_FOUND: " + device.getName());
                //找到一个，添加一个
                if (device.getName() != null) {
                    Log.d(TAG, "target device found..");
                    mDeviceList.add(device);//添加进去后更新
                    mAdapter.notifyDataSetChanged();//更新列表
                }
            } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {
                /* 可发现模式改变*/
                int scanMode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, 0);
                if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
                    setProgressBarIndeterminateVisibility(true);
                    showToast("可发现模式开启");
                } else {
                    setProgressBarIndeterminateVisibility(false);
                    showToast("可发现模式结束");
                }
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                /* 绑定模式改变*/
                BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (remoteDevice == null) {
                    showToast("no device");
                }
                int status = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 0);
                if (status == BluetoothDevice.BOND_BONDED) {
                    //连接成功
                    showToast("Bonded" + remoteDevice.getName());
                } else if (status == BluetoothDevice.BOND_BONDING) {
                    //连接中
                    showToast("Bonding" + remoteDevice.getName());
                } else if (status == BluetoothDevice.BOND_NONE) {
                    //取消连接
                    showToast("Not bond" + remoteDevice.getName());
                }
            }
        }
    };

    /* 通过菜单的响应事件，根据ItemId辨别响应事件*/
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.enable_visiblity) {
            //打开蓝牙可见性
            mController.enableVisibly(this);
        } else if (id == R.id.bluetooth_isenable) {
            //是否打开蓝牙
            mController.blueisenable();
            boolean ret = mController.blueisenable();
            showToast("Bluetooth is enable?" + ret);
        } else if (id == R.id.isSupport_BlueTooth) {
            //是否支持蓝牙
            mController.isSupportBlueTooth();
            boolean ret = mController.isSupportBlueTooth();
            showToast("Support BlueTooth?" + ret);
        } else if (id == R.id.turnOff_Bluetooth) {
            //关闭蓝牙
            mController.turnOffBlueTooth();
        } else if (id == R.id.findDevice_Bluetooth) {
            //查找设备并且在蓝牙列别视图展示出来这些查找到的蓝牙设备
            requestBlueToothPermission();//要求权限
            mAdapter.refresh(mDeviceList);//刷新设备，将发现的设备列表给mAdapter 并且刷新数据
            mController.findDevice();//查找设备

            mListview.setOnItemClickListener(bondDeviceClick);//给listview设置一个监听 点击即绑定

        }else if (id == R.id.bonded_device){
            //查看已绑定设备并且在蓝牙列别视图展示出来这些绑定的蓝牙设备
            mBondedDevice = mController.getBondedDeviceList();//获取绑定设备
            mAdapter.refresh(mBondedDevice);
            mListview.setOnItemClickListener(bondedDeviceClick);//给listview设置一个监听 点击即连接
        }else if (id == R.id.disconnect_enumeration){
            //断开连接列表
            connectThread.cancel();
            connectedThread.cancel();
        }else if(id == R.id.Open_thread){
            //打开线程
            serverThread = new ServerThread();//accept thread
            serverThread.start();
        }

        return super.onOptionsItemSelected(item);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    //未绑定的设备点击事件 点击即可绑定
    private AdapterView.OnItemClickListener bondDeviceClick = new AdapterView.OnItemClickListener() {
        @TargetApi(Build.VERSION_CODES.KITKAT)
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            BluetoothDevice device = mDeviceList.get(i);
            /* SDK版本需要高于4.4*/
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                device.createBond();//查找到设备后绑定设备 在通信前
            }
        }
    };

    /* 绑定的设备点击事件 点击即可连接 */
    private AdapterView.OnItemClickListener bondedDeviceClick = new AdapterView.OnItemClickListener() {
        @Override
        /* i是所点击item在适配器中的位置  l是当前点击的item在listview 里的第几行的位置，通常i与l的值相同。*/
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            if (mBondedDevice != null&& mBondedDevice.size()>0) {
                BluetoothDevice device = mBondedDevice.get(i);//获取选中行数的设备
                /* 如果连接过则重新连接*/
                if (connectThread != null) {
                    connectThread.cancel();
                }

                connectThread = new ConnectThread(device);
                connectThread.start();
            }else{
                Log.i("text","数组异常"+mBondedDevice);
            }
        }
    };

    /* 发送与接受和关闭蓝牙按钮监听*/
    public void onClick(View view){
        switch (view.getId()) {
            case R.id.turn_on_off: // 发送'0'或者'1'都可以
                //蓝牙适配器是否为空 蓝牙适配器是否可用
                if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
                    Toast.makeText(this, "蓝牙未开启", Toast.LENGTH_SHORT).show();
                    break;
                }
                if (connectedThread == null) {
                    Toast.makeText(this, "未连接设备", Toast.LENGTH_SHORT).show();
                    break;
                }
                Log.i("text","connectedThreadconnectedThread"+connectedThread);
                break;
            case R.id.clear_recv_view: // 清空接收框
                recvView.setText("");
                break;
            case R.id.delete_edit: // 清空接收框
                sendText.setText("");
                break;
            case R.id.send: // 发送数据，默认以"@#"结尾
                if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
                    Toast.makeText(this, "蓝牙未开启", Toast.LENGTH_SHORT).show();
                    return;
                }
                if (connectedThread == null) {
                    Toast.makeText(this, "未连接设备", Toast.LENGTH_SHORT).show();
                    break;
                }
                String inputText = sendText.getText().toString() + "#"; // 发送给单片机数据以"@#结尾"，这样单片机知道一条数据发送结束
                Toast.makeText(BlueToothActivity.this, inputText, Toast.LENGTH_SHORT).show();
                connectedThread.write(inputText.getBytes());
                break;
            default:
                break;

        }
    }



/////////////////////////////////////////////////////////////////////////////////////////////
public android.os.Handler handler  = new android.os.Handler() {
    /**
     * Message:Handler接收与处理的消息对象
     * 用于存放传递的数据；
     * 是主线程和子线程传递数据的载体
     * @param msg
     */
    public void handleMessage(Message msg) {
        Bundle bundle = null;
        String info = (String) msg.obj;
        switch (msg.what) {
            //接受数据
            case RECV_VIEW:
                //获取Message中存储的数据
                bundle = msg.getData();
                String recv = bundle.getString("recv");

                recvView.append(recv + "\n");
                scrollView.fullScroll(ScrollView.FOCUS_DOWN); // 滚动到底部
                Log.i("send___",recv);
                break;
            //发送数据
            case NOTICE_VIEW:
                //获取数据
                bundle = msg.getData();
                String notice = bundle.getString("notice");
                noticeView.setText(notice);
                Log.i("send",notice);
                break;
            case STATUS_CONNECT:
                Toast.makeText(BlueToothActivity.this, info,Toast.LENGTH_SHORT).show();
            default:
                break;
        }
    }
};
    // 服务端线程
    private class ServerThread extends Thread {
        public void run() {
            /*  try 和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个try…catch块。*/
            /* 如果异常发生了，则异常发生后面的代码不会执行，直接进入到catch块, 如果异常没有发生，则顺序执行try的代码块，不会进入到catch*/
            try {
                // 创建一个蓝牙服务器 参数分别：服务器名称、UUID
                mServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM,
                        UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));

                Message msg = new Message();
                //发送信息告诉客户服务器已开启
                msg.obj = "请稍候，正在等待客户端的连接...";
                msg.what = STATUS_CONNECT;
                handler.sendMessage(msg);//发送信息给UI 显示在屏幕上

                /* 接受客户端的连接请求 ，返回一个套接字 建立连接*/
                /* 当前阻塞监听到带有我们初始化的UUID参数的连接请求后作出响应，连接成功后返回一个BluetoothSocket对象*/
                // 通过socket连接设备，阻塞运行直到成功或抛出异常时
                socket = mServerSocket.accept();

                msg = new Message();
                //发送信息告诉客户已有客户端连接上服务端
                msg.obj = "客户端已经连接上！可以发送信息。";
                msg.what = STATUS_CONNECT;
                handler.sendMessage(msg);
                // 启动接受数据线程
                connectedThread = new ConnectedThread(socket);//读取数据的线程
                connectedThread.start();

            } catch (IOException e)//输入输出异常
            {
                e.printStackTrace();//在命令行打印异常信息在程序中出错的位置及原因。
            }
        }
    };


    /* 客户端线程*/
    public class ConnectThread extends Thread {
        //将一个临时对象分配给Socket，因为Socket是最终的
        private final String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";
        private final BluetoothDevice device;

        public ConnectThread(BluetoothDevice device) {
            this.device = device;
            //客户端socket
            BluetoothSocket tmp = null;
            // 用BluetoothSocket连接到给定的蓝牙设备
            try {
                // MY_UUID是应用程序的UUID，客户端代码使用相同的UUID
                // 这个设备的uuid绑定好之后
                tmp = this.device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));

            } catch (IOException e) {
                e.printStackTrace();
            }
            socket = tmp;
        }
        public void run() {
            bluetoothAdapter.cancelDiscovery();//取消发现
            try {
                // 通过socket连接设备，阻塞运行直到成功或抛出异常时
                socket.connect();
                // 在单独的线程中完成管理连接的工作
                connectedThread = new ConnectedThread(socket);
                connectedThread.start();
            } catch (IOException e) {
                // 如果无法连接则关闭socket并退出
                try {
                    socket.close();
                } catch (IOException ee) {
                    ee.printStackTrace();
                }
                return;
            }
        }
        /**
         * 取消正在进行的连接并关闭socket
         */
        public void cancel() {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }




    public class ConnectedThread extends Thread {
        private final InputStream inputStream;//输入流
        private final OutputStream outputStream;//输出流
        /* 将已经连接好的客户端套接字作为参数传入*/
        public ConnectedThread(BluetoothSocket mSocket) {
            socket = mSocket;
            InputStream input = null;
            OutputStream output = null;
            // 使用临时对象获取输入和输出流，因为成员流是最终的
            try {
                input = socket.getInputStream();
                output = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            this.inputStream = input;
            this.outputStream = output;
        }
        //死循环线程
        public void run() {
            //StringBuilder 对字符串的操作是直接改变字符串对象本身，而不是生成新的对象，所以新能开销小。
            StringBuilder recvText = new StringBuilder();
            // 用于流的缓冲存储
            byte[] buff = new byte[1024];
            // 从read()返回bytes 字节数
            int bytes;
            //发送信息
            //Bundle主要用于传递数据；它保存的数据，是以key-value(键值对)的形式存在的。
            Bundle tmpBundle = new Bundle();
            Message tmpMessage = new Message();
            tmpBundle.putString("notice", "连接成功");
            tmpMessage.what = NOTICE_VIEW;
            tmpMessage.setData(tmpBundle);
            handler.sendMessage(tmpMessage);
            // 持续监听InputStream，直到出现异常
            while (true) {
                try {
                    // 从InputStream读取数据
                    bytes = inputStream.read(buff);
                    //将buff以“ISO-8859-1”的编码方式转换为字节数组
                    String str = new String(buff, "ISO-8859-1");
                    //返回一个新字符串，它是此字符串的一个子字符串。该子字符串从指定的 0 处开始，直到索引 bytes - 1 处的字符
                    str = str.substring(0, bytes);
                    // 收到数据，单片机发送上来的数据以"#"结束，这样手机知道一条数据发送结束
                    Log.e("read", str);
                    //判断此字符串是否以指定的后缀结束。
                    if (!str.endsWith("#")) {
                        /*append()是将指定的字符串追加到此字符序列*/
                        recvText.append(str);
                        continue;
                    }
                    recvText.append(str.substring(0, str.length() - 1)); // 去除'#'

                    Bundle bundle = new Bundle();
                    Message message = new Message();

                    //向Message中添加数据
                    bundle.putString("recv", recvText.toString());
                    message.what = RECV_VIEW;
                    message.setData(bundle);
                    //发送数据
                    handler.sendMessage(message);


                    recvText.replace(0, recvText.length(), "");
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }

        public void write(byte[] bytes) {
            try {
                outputStream.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public void cancel() {
            try {
                socket.close();
                //为了彻底断开connectedThread的连接，所以给他赋值为null
                //没有将它赋值为空的时候，connectedThread的断开列举是不彻底的
                //可以将下面的注释了后加上Log来看看是否还会有值
                connectedThread = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}